class Tools {
    constructor() {
    }

    /**
     * 返回文件后缀
     * @param  {Object} file
     * @return {String}
     */
    getFilenameExt(file) {
        const types = file.name.split('.')
        return types[types.length - 1]
    }

    /**
     * 返回指定范围内的一个整数
     * @param  {Number} min
     * @param  {Number} max
     * @return {String}
     */
    rand(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min)
    }

    /**
     * 生成字符串组合
     * @param  {Number} size
     * @return {String}
     */
    randString(size) {
        let result = ''
        let allChar = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

        size = size || 1

        while (size--) {
            result += allChar.charAt(this.rand(0, allChar.length - 1))
        }

        return result
    }

    /**
     * 生成文件名
     * @param  {Object} file
     * @return {String}
     */
    randFilename(file) {
        return this.randString(this.rand(10, 100)) + Date.parse(new Date()) + '.' + this.getFilenameExt(file)
    }

    /**
     * 判断某个元素是否为字符串
     * @param  {String}  value
     * @return {Boolean}
     */
    isString(value) {
        return typeof value === 'string'
    }

    /**
     * 判断某个元素是否为函数
     * @param  {Function}  value
     * @return {Boolean}
     */
    isFunction(value) {
        return this.type(value) === 'function'
    }

    /**
     * 判断某个元素是否为数组
     * @param  {Array}  value
     * @return {Boolean}
     */
    isArray(value) {
        return Array.isArray(value)
    }

    /**
     * 判断某个元素是否为对象
     * @param  {Obejct}  value
     * @return {Boolean}
     */
    isObject(value) {
        return value !== null && typeof value === 'object'
    }

    /**
     * 判断某个元素是否为数值
     * @param  {Number}  value
     * @return {Boolean}
     */
    isNumber(value) {
        return typeof value === 'number'
    }

    /**
     * 判断某个元素是否为日期
     * @param  {Date}  value
     * @return {Boolean}
     */
    isDate(value) {
        return this.type(value) === '[object Date]'
    }

    /**
     * 判断某个元素是否为正则表达式
     * @param  {RegExp}  value
     * @return {Boolean}
     */
    isRegExp(value) {
        return this.type(value) === '[object RegExp]'
    }

    /**
     * 判断某个元素是否为File对象
     * @param  {Object}  obj
     * @return {Boolean}
     */
    isFile(obj) {
        return this.type(obj) === '[object File]'
    }

    /**
     * 判断某个元素是否为FormData对象
     * @param  {Object}  obj
     * @return {Boolean}
     */
    isFormData(obj) {
        return this.type(obj) === '[object FormData]'
    }

    /**
     * 判断某个元素是否为Blob对象
     * @param  {Object}  obj
     * @return {Boolean}
     */
    isBlob(obj) {
        return this.type(obj) === '[object Blob]'
    }

    /**
     * 判断某个元素是否为布尔值
     * @param  {boolean}  value
     * @return {Boolean}
     */
    isBoolean(value) {
        return typeof value === 'boolean'
    }

    /**
     * 判断某个元素是否为Promise对象
     * @param  {Function}  obj
     * @return {Boolean}
     */
    isPromiseLike(obj) {
        return obj && this.isFunction(obj.then)
    }

    /**
     * 判断数组类型
     * @param  {Array}  value
     * @return {Boolean}
     */
    isTypedArray(value) {
        const TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/
        return value && this.isNumber(value.length) && TYPED_ARRAY_REGEXP.test(this.type(value))
    }

    /**
     * 判断某个元素是否为ArrayBuffer对象
     * @param  {Object}  obj
     * @return {Boolean}
     */
    isArrayBuffer(obj) {
        return this.type(obj) === '[object ArrayBuffer]'
    }

    /**
     * 判断某个元素是否为defined
     * @param  {undefined}  value
     * @return {Boolean}
     */
    isDefined(value) {
        return typeof value !== 'undefined'
    }

    /**
     * 判断某个元素是否为undefined
     * @param  {undefined}  value
     * @return {Boolean}
     */
    isUndefined(value) {
        return typeof value === 'undefined'
    }

    /**
     * 判断某个元素是否为null
     * @param  {Null}  value
     * @return {Boolean}
     */
    isNull(value) {
        return value === null
    }

    /**
     * 判断某个元素是否为有限数
     * @param  {Number}  value
     * @return {Boolean}
     */
    isFinite(value) {
        return typeof value == 'number' && isFinite(value)
    }

    /**
     * 判断某个元素是否为自然数
     * @param  {Number}  value
     * @return {Boolean}
     */
    isNaN(value) {
        return this.isNumber(value) && value != +value
    }

    /**
     * 判断某个元素是否为错误类型
     * @param  {Object}  value
     * @return {Boolean}
     */
    isError(value) {
        return this.type(value) === '[object Error]'
    }

    /**
     * 删除字符串左右两端的空格
     * @param  {String} str
     * @return {String}
     */
    trim(str) {
        return this.isString(str) ? str.trim() : str
    }

    /**
     * 字符串转义
     * @param  {String} str
     * @return {String}
     */
    escapeForRegexp(str) {
        return str.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').replace(/\x08/g, '\\x08')
    }

    /**
     * 字符串转对象
     * @param  {String} str 'key1,key2,...'
     * @return {Object} in the form of {key1:true, key2:true, ...}
     */
    makeMap(str) {
        let obj = {}, items = str.split(',')
        for (let i = 0; i < items.length; i++) {
            obj[items[i]] = !0
        }
        return obj
    }

    /**
     * 判断数组中是否含有指定元素
     * @param  {Array} arr
     * @param  {Objext} obj
     * @return {Array}
     */
    includes(arr, obj) {
        return Array.prototype.indexOf.call(arr, obj) != -1
    }

    /**
     * 数组删除指定的元素，并返回元素的索引值
     * @param  {Array} array
     * @param  {String} value
     * @return {Number}
     */
    arrayRemove(array, value) {
        let index = array.indexOf(value)
        if (index >= 0) {
            array.splice(index, 1)
        }
        return index
    }

    /**
     * 日期增加分钟
     * @param  {Date} date
     * @param  {Number} minutes
     * @return {Date}
     */
    addDateMinutes(date, minutes) {
        date = new Date(date.getTime())
        date.setMinutes(date.getMinutes() + minutes || 0)
        return date
    }

    time_format(time) {
        let date = time || new Date()
        let month = parseInt(date.getMonth()) + 1
        return date.getYear() + '-' + month + '-' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes()
    }

    date_format(time) {
        let date = time || new Date()
        let month = parseInt(date.getMonth()) + 1
        return date.getFullYear() + '-' + month + '-' + date.getDate()
    }

    day_format() {
        let date = new Date()
        return date.getHours() + ':' + date.getMinutes()
    }

    nextDate(){

        let d = new Date()
        let time = new Date(d- 864000)
        let date = this.date_format(time)
        return date
    }

    /**
     * 对象解析出JSON字符串
     * @param  {Object} obj
     * @param  {Number} pretty
     * @return {Object}
     */
    toJson(obj, pretty) {
        if (this.isUndefined(obj)) return undefined
        if (!this.isNumber(pretty)) {
            pretty = pretty ? 2 : null
        }
        return JSON.stringify(obj, null, pretty)
    }

    /**
     * JSON字符串解析成对象
     * @param  {String} json
     * @return {Object}
     */
    fromJson(json) {
        return this.isString(json) ? JSON.parse(json) : json
    }

    /**
     * 扩展对象
     * @return {Object}
     */
    extend() {
        let src, copyIsArray, copy, name, options, clone,
            target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = !1;

        if (typeof target === 'boolean') {
            deep = target
            target = arguments[i] || {}
            i++
        }

        if (typeof target !== 'object' && !this.isFunction(target)) {
            target = {}
        }

        if (i === length) {
            target = this
            i--
        }

        for (; i < length; i++) {
            if ((options = arguments[i]) != null) {
                for (name in options) {
                    src = target[name]
                    copy = options[name]

                    if (target === copy) {
                        continue
                    }

                    if (deep && copy && (this.isPlainObject(copy) || (copyIsArray = this.isArray(copy)))) {
                        if (copyIsArray) {
                            copyIsArray = !1
                            clone = src && this.isArray(src) ? src : []
                        } else {
                            clone = src && this.isPlainObject(src) ? src : {}
                        }
                        target[name] = this.extend(deep, clone, copy)
                    } else if (copy !== undefined) {
                        target[name] = copy
                    }
                }
            }
        }
        return target
    }

    /**
     * 判断传入的参数是否为纯粹的对象，即直接量{}或new Object()创建的对象
     * @param  {[type]}  obj [description]
     * @return {Boolean}     [description]
     */
    isPlainObject(obj) {
        let getProto = Object.getPrototypeOf
        let class2type = {}
        let toString = class2type.toString
        let hasOwn = class2type.hasOwnProperty
        let fnToString = hasOwn.toString
        let ObjectFunctionString = fnToString.call(Object)
        let proto, Ctor
        if (!obj || this.type(obj) !== '[object Object]') {
            return !1
        }
        proto = getProto(obj)
        if (!proto) {
            return !0
        }
        Ctor = hasOwn.call(proto, 'constructor') && proto.constructor
        return typeof Ctor === 'function' && fnToString.call(Ctor) === ObjectFunctionString
    }

    /**
     * 判断对象是否为空
     * @param  {Object}  obj
     * @return {Boolean}
     */
    isEmptyObject(obj) {
        for (let i in obj)
            return !1
        return !0
    }

    /**
     * 判断对象的类型
     * @param  {Object} obj
     * @return {String}
     */
    type(obj) {
        const toString = Object.prototype.toString

        if (obj == null) {
            return obj + ''
        }

        return typeof obj === 'object' || typeof obj === 'function' ? toString.call(obj) || 'object' : typeof obj
    }

    /**
     * 合并对象并返回一个新的对象，目标对象自身也会改变
     * @param  {Array} args
     * @return {Object}
     */
    merge(...args) {
        return Object.assign(...args)
    }

    /**
     * 拷贝对象并返回一个新的对象
     * @param  {Object} obj
     * @return {Object}
     */
    clone(obj) {
        if (typeof obj !== 'object' || !obj) {
            return obj
        }
        let copy = {}
        for (let attr in obj) {
            if (obj.hasOwnProperty(attr)) {
                copy[attr] = obj[attr]
            }
        }
        return copy
    }

    /**
     * 删除对象上的指定属性并返回一个新的对象
     * @param  {Object} obj
     * @param  {Array} keys
     * @return {[type]}
     */
    omit(obj, keys) {
        let o = this.clone(obj)
        keys.forEach(key => {
            delete o[key]
        })
        return o
    }

    /**
     * 返回一个新数组，数组中的元素为指定属性的值
     * @param  {Array} arr
     * @param  {String} key
     * @return {Array}
     */
    pluck(arr, key) {
        if (typeof arr !== 'object' || arr.length === 0) {
            return []
        }
        if (!key) {
            return arr
        }
        return arr.map(a => a[key])
    }

    /**
     * 返回序列化的值
     * @param  {String} value
     * @return {String}
     */
    serializeValue(value) {
        if (this.isObject(value)) return this.isDate(value) ? value.toISOString() : this.toJson(value)
        return value
    }

    /**
     * 编码URI
     * @param  {String} value
     * @param  {String} pctEncodeSpaces
     * @return {String}
     */
    encodeUriQuery(value, pctEncodeSpaces) {
        return encodeURIComponent(value)
            .replace(/%40/gi, '@')
            .replace(/%3A/gi, ':')
            .replace(/%24/g, '$')
            .replace(/%2C/gi, ',')
            .replace(/%3B/gi, ';')
            .replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'))
    }

    /**
     * 对象序列化
     * @param  {Object} obj
     * @return {String}
     */
    paramSerializer(obj) {
        if (!obj) return ''
        let that = this
        let parts = []
        for (let key in obj) {
            const value = obj[key]
            if (value === null || that.isUndefined(value)) return
            if (that.isArray(value)) {
                value.forEach(function (v) {
                    parts.push(that.encodeUriQuery(key) + '=' + that.encodeUriQuery(that.serializeValue(v)))
                })
            } else {
                parts.push(that.encodeUriQuery(key) + '=' + that.encodeUriQuery(that.serializeValue(value)))
            }
        }
        return parts.join('&')
    }

    /**
     * 拼接URL
     * @param  {String} obj
     * @param  {Object} obj
     * @return {String}
     */
    buildUrl(url, obj) {
        const serializedParams = this.paramSerializer(obj)
        if (serializedParams.length > 0) {
            url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams
        }
        return url
    }


    getDateDiff(startDate, endDate) {
        let startTime = new Date(Date.parse(startDate.replace(/-/g, "/"))).getTime();
        let endTime = new Date(Date.parse(endDate.replace(/-/g, "/"))).getTime();
        let dates = Math.abs((startTime - endTime)) / (1000 * 60 * 60 * 24);
        return dates;
    }

    in_array(stringToSearch, arrayToSearch) {
        for (let s = 0; s < arrayToSearch.length; s++) {
            let thisEntry = arrayToSearch[s].toString();
            if (thisEntry == stringToSearch) {
                return true;
            }
        }
        return false;
    }

}

export default Tools